home *** CD-ROM | disk | FTP | other *** search
/ HPAVC / HPAVC CD-ROM.iso / pc / ABUSESRC.ZIP / AbuseSrc / imlib / port / dos4gw / video.c < prev   
Encoding:
C/C++ Source or Header  |  1996-01-31  |  11.7 KB  |  505 lines

  1. // Watcom graphics support
  2.  
  3.  
  4. #include "globals.hpp"
  5. #include "system.h"
  6. #include "video.hpp"
  7. #include "dos.h"
  8. #include "macs.hpp"
  9. #include "bitmap.h"
  10. #include "image.hpp"
  11. #include "palette.hpp"
  12. #include "jmalloc.hpp"
  13. #include "doscall.hpp"
  14. #include <conio.h>
  15.  
  16.  
  17. #define vga_getgraphmem() ((unsigned char *)VESA_video_mem)
  18. #define vga_setpage(x) (VESA_set_bank(x))
  19. #define WinAAttributes() vesa_mode_info[2]
  20. #define WinBAttributes() vesa_mode_info[3]
  21. #define WinGranularity() (*((unsigned short *)(vesa_mode_info+4)))
  22. #define WinSize() (*((unsigned short *)(vesa_mode_info+6)))
  23. #define WinASegment() (*((unsigned short *)(vesa_mode_info+8)))
  24. #define WinBSegment() (*((unsigned short *)(vesa_mode_info+10)))
  25. #define BankSize() vesa_mode_info[0x1c]
  26. #define WINDOW_A 0
  27. #define WINDOW_B 1
  28. #define WINDOW_DEFINED 1
  29. #define WINDOW_WRITABLE 4
  30.  
  31. unsigned char current_background;
  32. extern unsigned int xres,yres;
  33. extern palette *lastl;
  34. int vmode,VESA_write_window=0;
  35. image *screen;
  36. unsigned char *VESA_video_mem;
  37. char *dos_pal_memory=NULL;
  38. unsigned char *vesa_mode_info=NULL;
  39. int write_bank;
  40. int gran_shift=0;
  41.  
  42. #include <i86.h>
  43.  
  44. #define MKPTR(x)  ((   (((unsigned long)x)&0xffff0000)>>12)+  (((unsigned long)x)&0xffff))
  45.  
  46. #pragma pack( 1 ) // pack to bytes boundardy
  47.  
  48.  
  49. /* VESA video card capabilities block  */
  50. struct  ModeInfoBlock {
  51.     short  ModeAttributes;
  52.     char WinAAttributes;
  53.     char WinBAttributes;
  54.     unsigned short WinGranularity;
  55.     unsigned short  WinSize;
  56.     unsigned short  WinASegment;
  57.     unsigned short  WinBSegment;
  58.     unsigned long *WinFuncPtr;
  59.     short  BytesPerScanLine;
  60.     short  XResolution;
  61.     short  YResolution;
  62.     char XCharSize;
  63.     char YCharSize;
  64.     char NumberOfPlanes;
  65.     char BitsPerPixel;
  66.     char NumberOfBanks;
  67.     char MemoryModel;
  68.     char BankSize;
  69.     char NumberOfImagePages;
  70.     char SizeOfBank;
  71.     char RedMaskSize;
  72.     char RedFieldPosition;
  73.     char GreenMaskSize;
  74.     char GreenFieldPosition;
  75.     char BlueMaskSize;
  76.     char BlueFieldPosition;
  77.     char RsvdMaskSize;
  78.     char RsvdFieldPosition;
  79.     char DirectColorModeInfo;
  80.     char Reserved[216];
  81.     } vesa_info;
  82.  
  83. struct VgaInfoBlock
  84. {
  85.   unsigned char       VESASignature[4];
  86.   unsigned short      ver;
  87.   unsigned long       OEMStringPtr;
  88.   unsigned char       Capabilities[4];
  89.   unsigned long       VideoModePtr;
  90.   unsigned short      TotalMemory;
  91.   unsigned char       Reserved[236];
  92. } ;
  93.  
  94. #pragma pack( ) // pack back to normal
  95.  
  96.  
  97. void get_VESA_mode_info(ModeInfoBlock *s, unsigned short mode)
  98. {
  99.   int size=sizeof(ModeInfoBlock)<256 ? 256 : sizeof(ModeInfoBlock);
  100.   ModeInfoBlock *k=(ModeInfoBlock *)alloc_low_memory(size);
  101.   if (!k)
  102.   {
  103.     printf("Memory error : could not alloc low memory for VESA mode info structure\n");
  104.     exit(0);
  105.   }  
  106.  
  107.   rminfo rm;
  108.   memset(&rm,0,sizeof(rm));
  109.   rm.eax=0x4f01;
  110.   rm.ecx=mode;
  111.   rm.es=((long)(k))>>4;
  112.   rm.edi=0;        
  113.   RM_intr(0x10,&rm);
  114.  
  115.   memcpy(s,k,sizeof(ModeInfoBlock));
  116.   
  117.   free_low_memory(k);
  118. }
  119.  
  120. int usable_mode(ModeInfoBlock *m)
  121. {
  122.  
  123.   if ((m->ModeAttributes&1)==1 &&        // mode available?
  124.       (m->ModeAttributes&8)==8 &&        // color mode?
  125.       (m->ModeAttributes&16)==16 &&        // graphics mode?
  126.       (m->NumberOfPlanes==1)   &&        // packed pixel form
  127.       (m->BitsPerPixel==8)     &&        // 256 color mode
  128.       (m->MemoryModel==4)                // VESA packed pixel
  129.       )
  130.     return 1;
  131.   else return 0;
  132. }
  133.  
  134. int get_VESA_mode(char **s)
  135. {
  136.   int get_xres,get_yres,show_menu=1,found=0;
  137.  
  138.   if (sscanf(s[0],"%d",&get_xres)!=1 || sscanf(s[1],"%d",&get_yres)!=1)
  139.   { 
  140.     show_menu=1;
  141.     found=1;
  142.   }
  143.  
  144.   VgaInfoBlock *b=(VgaInfoBlock *)alloc_low_memory(sizeof(VgaInfoBlock));
  145.  
  146.   if (!b)
  147.   {
  148.     printf("Memory error : could not alloc low memory for VESA mode info structure\n");
  149.     exit(0);
  150.   }  
  151.   
  152.   rminfo rm;
  153.   memset(&rm,0,sizeof(rm));
  154.   rm.eax=0x4f00;
  155.   rm.es=((long)(b))>>4;
  156.   rm.edi=0;        
  157.   RM_intr(0x10,&rm);
  158.  
  159.   if (memcmp(b->VESASignature,"VESA",4))
  160.   {
  161.     printf("No VESA driver detected.  You need to install a VESA TSR.\n");
  162.     free_low_memory(b);
  163.     exit(0);
  164.   }
  165.   if ((b->ver>>8)==0 || (b->ver&&0xff)>2)
  166.   {
  167.     printf("Your VESA driver is out dated, please upgrade.\n");
  168.     free_low_memory(b);
  169.     exit(0);
  170.   }
  171.  
  172.   VESA_video_mem=(unsigned char *)MKPTR(b->VideoModePtr);
  173.   
  174.   printf("Video card info : %s\n",(char *)MKPTR(b->OEMStringPtr));
  175.   short *modes=(short *)MKPTR(b->VideoModePtr);   // type cast low mem pointer
  176.  
  177.   while (*modes!=-1 && !found)
  178.   {
  179.     struct ModeInfoBlock m;
  180.     get_VESA_mode_info(&m,*modes);
  181.     if (usable_mode(&m))
  182.     {                     // this is a usable mode
  183.       if (m.XResolution==get_xres && m.YResolution==get_yres)
  184.       {
  185.     free_low_memory(b);
  186.     return *modes;
  187.       }
  188.     }    
  189.     modes++;
  190.   }
  191.  
  192.   if (show_menu)
  193.   {
  194.     int i=1;
  195.     printf("Bad resoultion size or size not supported by VESA driver\n"
  196.        "Please choice one of the below :\n");
  197.     modes=(short *)MKPTR(b->VideoModePtr);
  198.     while (*modes!=-1)            // list all chosable modes
  199.     {
  200.       struct ModeInfoBlock m;
  201.       get_VESA_mode_info(&m,*modes);
  202.  
  203.       if (usable_mode(&m))
  204.       {
  205.     printf("%d) %d X %d\n",i,m.XResolution,m.YResolution);
  206.     i++;
  207.       }
  208.       modes++;
  209.     }
  210.  
  211.     int d=0;
  212.     do
  213.     {
  214.       fprintf(stderr,"Enter mode # (1-%d)>",i-1);
  215.       char ln[100];
  216.       fgets(ln,100,stdin);
  217.       if (!sscanf(ln,"%d",&d))
  218.         d=0;
  219.     } while (!d);
  220.     d--;
  221.  
  222.     modes=(short *)MKPTR(b->VideoModePtr);
  223.     while (*modes!=-1)
  224.     {
  225.       struct ModeInfoBlock m;
  226.       get_VESA_mode_info(&m,*modes);
  227.       if (usable_mode(&m))
  228.       {
  229.     if (d) d--;
  230.     else return *modes;
  231.       }
  232.       modes++;
  233.     }
  234.  
  235.     printf("Your VESA driver is reporting incorrect information, try getting\n"
  236.        "univbe or univesa from any simtel mirror ftp site such as\n"
  237.        "wuarchive.wustl.edu.\n");
  238.     free_low_memory(b);
  239.     exit(0);
  240.   }
  241.  
  242.   free_low_memory(b);
  243.   return found;
  244. }
  245.  
  246. void VESA_set_bank(int x)
  247. {
  248.   if (vmode!=0x13)
  249.   {
  250.     rminfo rm;
  251.     memset(&rm,0,sizeof(rm));
  252.     rm.eax=0x4f05;
  253.     rm.ebx=VESA_write_window;
  254.     rm.edx=x<<gran_shift;
  255.     RM_intr(0x10,&rm);
  256.   }
  257. }
  258.  
  259. int VESA_get_mode()
  260. {
  261.   rminfo rm;
  262.   memset(&rm,0,sizeof(rm));
  263.   rm.eax=0x4f03;
  264.   RM_intr(0x10,&rm);
  265.   return rm.ebx&0xffff;
  266. }
  267.  
  268. int VESA_set_mode(int mode)
  269. {
  270.   rminfo rm;
  271.   memset(&rm,0,sizeof(rm));
  272.   if (mode!=19 && mode!=3)
  273.   {
  274.     rm.eax=0x4f02;
  275.     rm.ebx=mode;
  276.     RM_intr(0x10,&rm);
  277.     vmode=mode;
  278.  
  279.     if (VESA_get_mode()==mode)
  280.     {
  281.       get_VESA_mode_info(&vesa_info,mode);
  282.  
  283.       if ((vesa_info.WinAAttributes & WINDOW_DEFINED) &&
  284.       (vesa_info.WinAAttributes & WINDOW_WRITABLE))
  285.       {
  286.         VESA_write_window=WINDOW_A;
  287.     VESA_video_mem=(unsigned char *)((long)vesa_info.WinASegment<<4);
  288.       }
  289.       else if ((vesa_info.WinBAttributes & WINDOW_DEFINED) &&           
  290.            (vesa_info.WinBAttributes & WINDOW_WRITABLE))
  291.       {
  292.         VESA_write_window=WINDOW_B;
  293.     VESA_video_mem=(unsigned char *)((long)vesa_info.WinBSegment<<4);
  294.       }
  295.       else VESA_video_mem=(unsigned char *)0xa0000;
  296.  
  297.       xres=vesa_info.XResolution-1;
  298.       yres=vesa_info.YResolution-1;
  299.  
  300.       if (vesa_info.WinGranularity==1)  // 1K pages
  301.         gran_shift=6;
  302.       else if (vesa_info.WinGranularity==2)  // 2K pages
  303.         gran_shift=5;
  304.       else if (vesa_info.WinGranularity==4)  // 4K pages
  305.         gran_shift=4;
  306.       else if (vesa_info.WinGranularity==8)  // 8K pages
  307.         gran_shift=3;
  308.       else if (vesa_info.WinGranularity==16)  // 16K pages
  309.         gran_shift=2;
  310.       else if (vesa_info.WinGranularity==32)  // 16K pages
  311.         gran_shift=1;
  312.       else if (vesa_info.WinGranularity==64)  // 16K pages
  313.         gran_shift=0;
  314.       else
  315.       {
  316.     printf("VESA : window granularity not supported (%d)\n",vesa_info.WinGranularity);
  317.     exit(0);
  318.       }
  319.  
  320.       
  321.  
  322. //      exit(0);
  323.       return 1;
  324.     } else return 0;
  325.   }
  326.   else
  327.   {
  328.     vmode=mode;
  329.     rm.eax=mode;
  330.     RM_intr(0x10,&rm);
  331.     VESA_video_mem=(unsigned char *)0xa0000;
  332.     VESA_write_window=WINDOW_A;
  333.     xres=320-1;
  334.     yres=200-1;
  335.     return 1;
  336.   }
  337. }
  338.  
  339. void set_mode(int mode, int argc, char **argv)
  340. {
  341.   int i,j;
  342.   
  343.   xres=320; yres=200;
  344.  
  345.   for (i=1;i<argc;i++)
  346.     if (!strcmp(argv[i],"-size"))
  347.       mode=get_VESA_mode(argv+i+1);
  348.  
  349.  
  350.   if (!VESA_set_mode(mode))
  351.   {
  352.     printf("Unable to set video mode.  The correct VESA driver is not loaded\n"
  353.            "or it does not support this video mode.\n");
  354.     exit(1);
  355.   }
  356.  
  357.   screen=new image(xres+1,yres+1,NULL,2);
  358.   screen->clear();
  359.   update_dirty(screen);
  360.  
  361. }
  362.  
  363. int get_vmode()
  364. { return vmode; }
  365.  
  366. void close_graphics()
  367. {
  368.   if (lastl)
  369.     delete lastl;
  370.   lastl=NULL;
  371.   VESA_set_mode(3);  // switch to text mode
  372.   delete screen;
  373. }
  374.  
  375. void put_part(image *im, int x, int y, int x1, int y1, int x2, int y2)
  376. {
  377.   unsigned short screen_off;
  378.   int i,ys,ye,xs,xe,page,last_page=-1,yy;
  379.   long breaker;
  380.   unsigned char *screen_addr,*line_addr;
  381.  
  382.   if (y>(int)yres || x>(int)xres) return ;
  383.   CHECK(y1>=0 && y2>=y1 && x1>=0 && x2>=x1);
  384.  
  385.  
  386.   if (y<0)
  387.   { y1+=-y; y=0; }
  388.   ys=y1;
  389.   if (y+(y2-y1)>=(int)yres)
  390.     ye=(int)yres-y+y1-1;
  391.   else ye=y2;
  392.  
  393.   if (x<0)
  394.   { x1+=-x; x=0; }
  395.   xs=x1;
  396.   if (x+(x2-x1)>=(int)xres)
  397.     xe=(int)xres-x+x1-1;
  398.   else xe=x2;
  399.   if (xs>xe || ys>ye) return ;
  400.  
  401.   int virtual_screen_width=im->width();
  402.   line_addr=im->scan_line(ys)+xs;
  403.  
  404.   for (yy=ys;yy<=ye;yy++)
  405.   {
  406.     page=(long)y*(long)(xres+1)>>16;
  407.     if (page!=last_page)
  408.     { last_page=page;
  409.       vga_setpage(page);
  410.     }
  411.  
  412.     // find the memory offset for the scan line of interest
  413.     screen_off=((long)y*(long)(xres+1))&0xffff;
  414.  
  415.     // breaker is the number of bytes beofer the page split
  416.     breaker=(long)0xffff-(long)screen_off+1;
  417.  
  418.     if (breaker>x+xe-xs)
  419.       memcpy(vga_getgraphmem()+screen_off+x,line_addr,xe-xs+1);
  420.     else if (breaker<=x)
  421.     { last_page++;
  422.       vga_setpage(last_page);
  423.       memcpy(vga_getgraphmem()+x-breaker,line_addr,xe-xs+1);
  424.     }
  425.     else
  426.     {
  427.       memcpy(vga_getgraphmem()+screen_off+x,line_addr,breaker-x);
  428.       last_page++;
  429.       vga_setpage(last_page);
  430.       memcpy(vga_getgraphmem(),line_addr+breaker-x,xe-xs-(breaker-x)+1);
  431.     }
  432.     y++;
  433.     line_addr+=virtual_screen_width;
  434.   }
  435. }
  436.  
  437. void put_image(image *im, int x, int y)
  438. { put_part(im,x,y,0,0,im->width()-1,im->height()-1); }
  439.  
  440.  
  441. void update_dirty(image *im, int xoff, int yoff)
  442. {
  443.  
  444.   int count,x1,y1,x2,y2;
  445.   dirty_rect *dr,*q;
  446.   image *Xim;
  447.   CHECK(im->special);  // make sure the image has the ablity to contain dirty areas
  448.   if (im->special->keep_dirt==0)
  449.     put_image(im,0,0);
  450.   else
  451.   {
  452.     count=im->special->dirties.number_nodes();
  453.     if (!count) return;  // if nothing to update, return
  454.     dr=(dirty_rect *)im->special->dirties.first();
  455.     while (count>0)
  456.     {
  457. /*      if (dr->dx1+xoff<0) dr->dx1=0-xoff;
  458.       if (dr->dy1+yoff<0) dr->dy1=0-yoff;
  459.       if (dr->dx2+xoff>xres) dr->dx2=xres-xoff;
  460.       if (dr->dy2+yres>yres) dr->dy2=yres-yoff;
  461.       if (dr->dx1<=dr->dx2 && dr->dy1<=dr->dy2) */
  462.       put_part(im,dr->dx1+xoff,dr->dy1+yoff,dr->dx1,dr->dy1,dr->dx2,dr->dy2);
  463.       q=dr;
  464.       dr=(dirty_rect *)dr->next();
  465.       im->special->dirties.unlink((linked_node *)q);
  466.       delete q;
  467.       count--;
  468.     }
  469.   }
  470. }
  471.  
  472.  
  473. void palette::load()
  474. {
  475.   int i;
  476.   unsigned char *a=(unsigned char *)addr();
  477.   if (lastl)
  478.     delete lastl;
  479.   lastl=copy();
  480.  
  481.   outp(0x3c8,0);
  482.   for (i=0;i<768;i++,a++)
  483.     outp(0x3c9,(*a)>>2);
  484.  
  485. }
  486.  
  487. void palette::load_nice()
  488. { load(); }
  489.  
  490.  
  491. void image::make_page(short width, short height, unsigned char *page_buffer)
  492. {
  493.   if (page_buffer)
  494.     data=page_buffer;
  495.   else data=(unsigned char *)jmalloc(width*height,"image::data");
  496. }
  497.  
  498. void image::delete_page()
  499. {
  500.   if (!special || !special->static_mem)
  501.     jfree(data);      
  502. }
  503.  
  504.  
  505.